package ikar.nrd.fillingref.generator;

import ikar.nrd.model.ChoiseColorStyle;
import ikar.nrd.model.FillingRef;
import ikar.nrd.model.XmlNamespaceManager;

import java.util.ArrayList;
import java.util.List;

import javax.swing.tree.DefaultMutableTreeNode;

import org.xml.sax.SAXException;

import com.sun.xml.xsom.XSAttributeUse;
import com.sun.xml.xsom.XSComplexType;
import com.sun.xml.xsom.XSContentType;
import com.sun.xml.xsom.XSModelGroup;
import com.sun.xml.xsom.XSParticle;
import com.sun.xml.xsom.XSSchema;
import com.sun.xml.xsom.XSSchemaSet;
import com.sun.xml.xsom.XSTerm;
import com.sun.xml.xsom.parser.XSOMParser;

public class XSDProcessor extends CoreScriptGenerator {

	List<String> componentsHierarhiList = new ArrayList<String>();

	public XSDProcessor(String patternId) {
		super(patternId);
	}

	public DefaultMutableTreeNode getXsdElementHierarchy(String xsdTypeName, String xmlRootNodeName, String patternId) throws Exception {
		try {
			XSOMParser parser = new XSOMParser();
			parser.parse(getClass().getClassLoader().getResource("/fpml/nsd-ext-merged-schema.xsd"));
			// parser.parse(uri);
			XSSchemaSet sset = parser.getResult();
			XSSchema s = sset.getSchema(1);
			XSComplexType complexType = s.getComplexType(xsdTypeName);
			if (complexType == null) {
				parser = new XSOMParser();
				parser.parse(getClass().getClassLoader().getResource("/fpml/fpml-recordkeeping-merged-schema.xsd"));
				sset = parser.getResult();
				s = sset.getSchema(1);
				complexType = s.getComplexType(xsdTypeName);
			}

			XSContentType xsContentType = complexType.getContentType();
			XSParticle particle = xsContentType.asParticle();
			FillingRef xsdTypeFillRef = new FillingRef("", "", xmlRootNodeName, patternId);
			String nodePrefix = "nsd";
			if (particle != null) {
				nodePrefix = XmlNamespaceManager.getLinkByUri(particle.getOwnerSchema().getTargetNamespace());
			}
			xsdTypeFillRef.setFullPath(nodePrefix + ":" + xmlRootNodeName);
			xsdTypeFillRef.setPlateCode(xsdTypeName.toUpperCase());
			DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(xsdTypeFillRef);

			// DefaultMutableTreeNode tradeNode = CommonFIeldsGenerator.getTradeElement(); tradeNode.add(rootNode);
			fillXsdElementHierarhy(particle, xsdTypeFillRef, rootNode, null);
			return rootNode;
		} catch (SAXException e) {
			throw e;
		} catch (Exception e) {
			throw e;
		}
	}

	private void fillXsdElementHierarhy(XSParticle particle, FillingRef parentFillingRef, DefaultMutableTreeNode rootNode, Integer choiseIndex) {
		{
			if (particle != null) {
				XSTerm term = particle.getTerm();
				if (term.isModelGroup()) {
					XSModelGroup modGroup = term.asModelGroup();
					boolean isChoise = modGroup.getCompositor() == XSModelGroup.CHOICE;
					if (isChoise) {
						if (choiseIndex != null) {
							choiseIndex++;
						} else {
							choiseIndex = 0;
						}
						for (XSParticle part : modGroup.getChildren()) {
							fillXsdElementHierarhy(part, parentFillingRef, rootNode, choiseIndex != null ? choiseIndex++ : null);
						}
						choiseIndex = null;
					} else {
						for (XSParticle part : modGroup.getChildren()) {
							fillXsdElementHierarhy(part, parentFillingRef, rootNode, choiseIndex);
						}
					}
				} else if (term.isElementDecl() && !componentsHierarhiList.contains(particle.getTerm().asElementDecl().getName())) {
					List<DefaultMutableTreeNode> attributesTreeNodes = new ArrayList<DefaultMutableTreeNode>();
					FillingRef fillingRefRow = new FillingRef();
					fillingRefRow.setXsdStyleClass(ChoiseColorStyle.getStyleClassName(choiseIndex));
					DefaultMutableTreeNode currentTreeNode = new DefaultMutableTreeNode(fillingRefRow);

					XSComplexType complexType = term.asElementDecl().getType().asComplexType();
					String currentNodeName = term.asElementDecl().getName();
					String currentElementPlateCode = parentFillingRef.getPlateCode() != null ? parentFillingRef.getPlateCode() + "_" + currentNodeName.toUpperCase() : currentNodeName.toUpperCase();
					fillingRefRow.setFullPath(getFullPath(parentFillingRef, term));
					fillingRefRow.setSelected(true);

					if (complexType == null) {
						fillingRefRow.setXpath(currentNodeName);
						fillingRefRow.setPlateCode(currentElementPlateCode);
						fillingRefRow.setParentPlateCode(parentFillingRef.getPlateCode());
						parentFillingRef.setSelected(false);
						rootNode.add(currentTreeNode);
						System.out.println(currentNodeName);
					} else {
						if (complexType.getDeclaredAttributeUses().size() > 0) {
							for (XSAttributeUse attribute : complexType.getDeclaredAttributeUses()) {
								if (attribute.getDecl().getName().contains("Scheme")) {
									String schemaAttribute = "[" + attribute.getDecl().getName() + "=''http://repository.nsd.ru/coding-scheme/" + term.asElementDecl().getName() + "(bsdrus)]";
									continue;
								}
								String attributeName = attribute.getDecl().getName();
								String attrPlateCode = currentElementPlateCode + "_" + attributeName.toUpperCase();

								FillingRef attrFillingRefRow = new FillingRef();
								attrFillingRefRow.setXpath("@" + attributeName);
								attrFillingRefRow.setPlateCode(attrPlateCode);
								attrFillingRefRow.setParentPlateCode(currentElementPlateCode);
								attrFillingRefRow.setAttribute(true);
								attrFillingRefRow.setSelected(true);
								attrFillingRefRow.setXsdStyleClass(ChoiseColorStyle.getStyleClassName(choiseIndex));
								attrFillingRefRow.setFullPath(CoreUtils.isEmpty(fillingRefRow.getFullPath()) ? attributeName : fillingRefRow.getFullPath() + "/" + "@" + attributeName);
								attributesTreeNodes.add(new DefaultMutableTreeNode(attrFillingRefRow));
							}
						}
						fillingRefRow.setXpath(currentNodeName);
						fillingRefRow.setPlateCode(currentElementPlateCode);
						fillingRefRow.setParentPlateCode(parentFillingRef.getPlateCode());
						parentFillingRef.setSelected(false);
						for (DefaultMutableTreeNode attribute : attributesTreeNodes) {
							currentTreeNode.add(attribute);
						}
						rootNode.add(currentTreeNode);

						componentsHierarhiList.add(currentNodeName);
						System.out.println(currentNodeName);
						fillXsdElementHierarhy(complexType.getContentType().asParticle(), fillingRefRow, currentTreeNode, choiseIndex);
						componentsHierarhiList.remove(currentNodeName);
					}
				} else if (term.isModelGroupDecl()) {
					XSModelGroup modGroup = term.asModelGroupDecl().getModelGroup();
					boolean isChoise = modGroup.getCompositor() == XSModelGroup.CHOICE;
					if (isChoise) {
						if (choiseIndex != null) {
							choiseIndex++;
						} else {
							choiseIndex = 0;
						}
						for (XSParticle part : modGroup.getChildren()) {
							fillXsdElementHierarhy(part, parentFillingRef, rootNode, choiseIndex != null ? choiseIndex++ : null);
						}
						choiseIndex = null;
					} else {
						for (XSParticle part : modGroup.getChildren()) {
							fillXsdElementHierarhy(part, parentFillingRef, rootNode, choiseIndex);
						}
					}
				}
			}
		}
	}

	private String getFullPath(FillingRef parentFillingRef, XSTerm term) {
		String nodePrefix = XmlNamespaceManager.getLinkByUri(term.asElementDecl().getTargetNamespace());
		String currentXpath = nodePrefix + ":" + getClearValue(term.asElementDecl().getName());
		return CoreUtils.isEmpty(parentFillingRef.getFullPath()) ? currentXpath : parentFillingRef.getFullPath() + "/" + currentXpath;
	}

}
